package com.luty.rpc.client;

import com.luty.rpc.bean.RpcRequest;
import com.luty.rpc.bean.RpcResponse;
import com.luty.rpc.register.ServiceDiscover;
import com.luty.rpc.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * Created by liuyunxin on 2017/7/2.
 */
public class RpcProxy {
    private static final Logger LOGGER = LoggerFactory.getLogger(RpcProxy.class);
    private String serviceAddress;
    private ServiceDiscover discover;
    public RpcProxy(String serviceAddress){this.serviceAddress = serviceAddress;}
    public RpcProxy(ServiceDiscover discover){this.discover = discover;}

    public <T> T create(final Class<T> interfaceClass) {return create(interfaceClass, "");}

    public <T> T create(final Class<T> interfaceClass, final String serviceVersion){
        return (T) Proxy.newProxyInstance(
                interfaceClass.getClassLoader(),
                new Class<?>[]{interfaceClass},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        RpcRequest request = new RpcRequest();
                        request.setRequestId(UUID.randomUUID().toString());
                        request.setInterfaceName(method.getDeclaringClass().getName());
                        request.setServiceVersion(serviceVersion);
                        request.setMethodName(method.getName());
                        request.setParameterTypes(method.getParameterTypes());
                        request.setParameters(args);
                        //获取RPC服务地址
                        LOGGER.debug("discover exist:{}", discover != null);
                        if(discover != null){
                            String serviceName = interfaceClass.getName();
                            if(!StringUtil.isEmpty(serviceVersion)){
                                serviceName += serviceVersion;
                            }
                            LOGGER.debug("serviceName:{}",serviceName);
                            serviceAddress = discover.discover(serviceName);
                            //LOGGER.debug("discover service: {} => {}", serviceName, serviceAddress);
                        }
                        if (StringUtil.isEmpty(serviceAddress)) {
                            throw new RuntimeException("server address is empty");
                        }
                        String[] array = StringUtil.split(serviceAddress,":");
                        String host = array[0];
                        int port = Integer.parseInt(array[1]);
                        // 创建 RPC 客户端对象并发送 RPC 请求
                        RpcClient client = new RpcClient(host, port);
                        long time = System.currentTimeMillis();
                        RpcResponse response = client.send(request);
                        LOGGER.debug("time: {}ms", System.currentTimeMillis() - time);
                        if (response == null) {
                            throw new RuntimeException("response is null");
                        }
                        // 返回 RPC 响应结果
                        if (response.hasException()) {
                            throw response.getException();
                        } else {
                            return response.getResult();
                        }
                    }
                }
        );
    }

}
